#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#    提供python操作word的接口
#

import win32com.client
import os, sys
import re
import win32api

if sys.path[-1]!='..': sys.path.append('..')

from common.cglobal import *

'''
 
 使用word进行解析的重点在于：
   使用详细设计模板时，需要添加相应的标签，并最好有单独的一节（如，最后一节），
   此时可以通过选定标签的开始、结束，通过复制和粘贴来进行

'''

tmp_begin="tmp_begin"
tmp_end="tmp_end"
dd_begin="dd_begin"
dd_end="dd_end"

#_template_name=os.path.dirname(__file__)+'/../user/_template.doc'
#_template_name=os.path.split(os.path.abspath(sys.argv[0]))[0]+'/user/_template.doc'
_template_short='/user/_template.doc'
_dst_name="dst.doc"

DD_PROTO    =1  # 原型
DD_BRIEF    =2  # 概述
DD_PARAM    =3  # 参数
DD_RETURN   =4  # 返回值
DD_REF      =5  # 引用函数
DD_GVAR_IN  =6  # 引用的全局变量
DD_GVAR_OUT =7  # 修改的全局变量
DD_DETAIL   =8  # 详细描述

# WdUnits 枚举 
wdCell		           = 12	#单元格。 
wdCharacter		       = 1	#字符。 
wdCharacterFormatting  = 13	#字符格式。 
wdColumn		       = 9	#列。 
wdItem		           = 16	#所选项。 
wdLine		           = 5	#一个线段。 
wdParagraph		       = 4	#段落。 
wdParagraphFormatting  = 14	#段落格式。 
wdRow		           = 10	#行。 
wdScreen		       = 7	#屏幕尺寸。 
wdSection		       = 8	#一节。 
wdSentence		       = 3	#句子。 
wdStory		           = 6	#部分。 
wdTable		           = 15	#一个表格。 
wdWindow		       = 11	#窗口。 
wdWord		           = 2	#字。
		
# WdMovementType 枚举
wdExtend    = 1 # 将所选内容的末尾扩展到指定单位的末尾。
wdMove      = 0 # 将所选内容折叠到插入点中并移到指定单位的末尾。默认值。

'''
# WdSaveOptions 枚举  
wdDoNotSaveChanges 0 不保存待定的更改。 
wdPromptToSaveChanges -2 提示用户保存待定更改。 
wdSaveChanges -1 自动保存待定更改，而不提示用户。 

# WdOriginalFormat枚举 
wdOriginalDocumentFormat 1 原始文档格式。 
wdPromptUser 2 提示用户选择文档格式。 
wdWordDocument 0 Microsoft Word 文档格式。 
'''

def make_main_title(name):
    return u'子函数'+name

def make_table_title(name):
    return u'函数'+name+u'描述表'

def make_chart_title(name):
    return u'函数'+name+u'流程图'

# function: get directory of current script, if script is built
#   into an executable file, get directory of the excutable file
def current_file_directory():
    #获取脚本路径
    if getattr(sys, 'frozen', False):
        #print "absEXE", sys.executable
        return os.path.dirname(sys.executable)
    else:
        return os.path.dirname(os.path.abspath(sys.argv[0]))

class cword:
    def __init__(self, name=''):
        self.word = win32com.client.Dispatch("Word.Application")
        self.ver = int(float(self.word.Version.decode("utf-8")))
        # 增加一个display alert的选项
        self.word.DisplayAlerts = 0
        self.word.Visible = 1
        # 设置默认的相关问题
        self.absdir = current_file_directory()

        if os.path.exists(self.absdir+'/..'+_template_short):
            self._template_name=self.absdir+'/..'+_template_short
        elif os.path.exists(self.absdir+_template_short):
            self._template_name=self.absdir+_template_short
        else:
            self._template_name="empty.doc"

        #print "###", self.absdir, self._template_name
        if (name!=''):
            self.filename = get_full_name(name)
        else:
            self.filename = self._template_name

    def open_default(self, output=''):
        print "open_default:", self.filename
        try:
            # 尝试打开已有的文件
            self.word.Documents(win32api.GetShortPathName(self.filename)).Activate()
            #self.word.Documents(self.filename).Activate()
        except:
            try:
                self.word.Documents.Open(win32api.GetShortPathName(self.filename))
                #self.word.Documents.Open(self.filename)
            except Exception, err:
                print "err"
                print err
                if (1):#(len(err) > 4):
                    print err[1]
                    print err[2][1]
                    print err[2][2].split('\r')[0]
        
        print 'Opening word:', output
        if output != '':
            self.word.ActiveDocument.SaveAs(output)
            print 'Save as:', output

    def open(self):
        self.word.Documents(_dst_name).Activate()

    def open_from_template(self, name=''):
        if (name!=''):
            full_name = get_full_name(name)
        else:
            full_name = get_full_name(_dst_name)

        tfull_name = self._template_name

        print 'Opening word:', full_name

        try:
            # 尝试打开已有的文件
            self.word.Documents(full_name).Activate()
        except:
            print 'Opening failed:', full_name
            self.word.Documents.Open(tfull_name)
            # 另存一份
            self.word.ActiveDocument.SaveAs(full_name)
        

    def close():
        self.word.ActiveDocument.Close()

    def get_bookmark_range(self, bm1=dd_begin, bm2=dd_end):
        self.word.ActiveDocument.Bookmarks(bm2).Select()
        p2 = self.word.Selection.End
        self.word.ActiveDocument.Bookmarks(bm1).Select()
        p1 = self.word.Selection.End
        range = self.word.ActiveDocument.Range(p1, p2)
        return range

    def insert_fun(self, title, finfo=None):
        try:
            if self.word.ActiveWindow.View.ReadingLayout == True:
                print "###Turn off reading"
                # 设置编辑模式
                self.word.ActiveWindow.View.ReadingLayout = False
                #self.word.Selection.EscapeKey()
        finally:
            pass
        range = self.copy_detail_design(title)
        self.update_detail_table(range.Tables(1), title, finfo)
        self.update_all_field()

    def copy_detail_design(self, title):
        # 统计两个不同的书签的位置
        range = self.get_bookmark_range()
        range.Copy()
        
        # 定位到模板之上一行
        self.word.ActiveDocument.Bookmarks("dd_begin").Select()
        self.word.Selection.MoveUp(wdLine, 1)
        
        # 添加临时书签，并粘贴
        self.word.Selection.Bookmarks.Add (tmp_begin)
        self.word.Selection.Paste()
        self.word.Selection.Bookmarks.Add (tmp_end)

        # 定位到临时书签头
        self.word.ActiveDocument.Bookmarks(tmp_begin).Select()

        # 替换顶级标题
        self.word.Selection.EndKey(wdLine, wdExtend)
        self.word.Selection.TypeText(make_main_title(title))

        # 更新表标题
        self.word.Selection.MoveDown(wdLine, 2)
        self.word.Selection.EndKey(wdLine, wdMove)
        self.word.Selection.TypeText(make_table_title(title))

        # 定位到临时书签尾部，更新图片
        self.word.ActiveDocument.Bookmarks(tmp_end).Select()
        self.word.Selection.MoveUp(wdLine, 1)
        self.word.Selection.EndKey(wdLine, wdMove)
        self.word.Selection.TypeText(make_chart_title(title))

        return self.get_bookmark_range(tmp_begin, tmp_end)

    def goto_home(self):
        self.word.Selection.HomeKey(wdStory)

    def find_text(self, keyword):
        # 两个比选的参数，返回true表示找到
        return self.word.Selection.Find.Execute(FindText=keyword, Forward=True)

    def update_detail_table(self, table, title, dinfo):
        if dinfo is None:
            table.Cell(DD_PROTO , 2).Range.InsertAfter(title)
            table.Cell(DD_BRIEF , 2).Range.InsertAfter(title+' b')
            table.Cell(DD_PARAM , 2).Range.InsertAfter(title+' c')
            table.Cell(DD_RETURN, 2).Range.InsertAfter(title+' d')
            table.Cell(DD_REF   , 2).Range.InsertAfter(title+' e')
            table.Cell(DD_DETAIL, 2).Range.InsertAfter(title+' f')
        else:
            # 插入相关
            table.Cell(DD_PROTO , 2).Range.InsertAfter(dinfo['proto'])
            table.Cell(DD_BRIEF , 2).Range.InsertAfter(dinfo['brief'])
            table.Cell(DD_PARAM , 2).Range.InsertAfter(dinfo['param'])
            table.Cell(DD_RETURN, 2).Range.InsertAfter(dinfo['return'])
            table.Cell(DD_REF   , 2).Range.InsertAfter(dinfo['fcall'])
            table.Cell(DD_GVAR_IN   , 2).Range.InsertAfter(dinfo['gvarin'])
            table.Cell(DD_GVAR_OUT  , 2).Range.InsertAfter(dinfo['gvarout'])
            table.Cell(DD_DETAIL, 2).Range.InsertAfter(dinfo['details'])

    def insert_visio_pic(self, visio):
        # assume the copy-paste board has been filled by visio chart
        self.word.ActiveDocument.Bookmarks(tmp_end).Select()
        self.word.Selection.MoveUp(wdLine, 2)
        # PastedAndFormat, 
        visio.copy2sys()
        self.word.Selection.Paste()

    def delete_template(self):
        range = self.get_bookmark_range()
        range.Delete()

    def update_all_field(self):
        # 全选，更新
        self.word.Selection.WholeStory()
        self.word.Selection.Fields.Update()
        #self.word.Selection.EscapeKey()
        self.word.ActiveDocument.Bookmarks(tmp_end).Select()

    def update_file_field(self):
        self.word.Selection.WholeStory()
        self.word.Selection.Fields.Update()

if __name__ == "__main__":
    #os.system("del "+dst_name)
    if len(sys.argv)>1:
        print "Testing word operation!"
        w = cword()
        w.open_from_template()
        w.insert_fun(sys.argv[1])
    else:
        prog = sys.argv[0].split('\\')[-1]
        print 'Usage:' + prog + ' function'
        print 'using', _template_name
